/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2014 abel533@gmail.com
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package com.javass.mybatis.plugin;

import java.sql.SQLException;
import java.util.Date;
import java.util.List;
import java.util.Properties;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.factory.DefaultObjectFactory;
import org.apache.ibatis.reflection.wrapper.DefaultObjectWrapperFactory;
import org.mybatis.generator.api.CommentGenerator;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.dom.java.CompilationUnit;
import org.mybatis.generator.api.dom.java.Field;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.api.dom.java.InnerClass;
import org.mybatis.generator.api.dom.java.InnerEnum;
import org.mybatis.generator.api.dom.java.Interface;
import org.mybatis.generator.api.dom.java.JavaElement;
import org.mybatis.generator.api.dom.java.Method;
import org.mybatis.generator.api.dom.xml.XmlElement;
import org.mybatis.generator.config.MergeConstants;
import org.mybatis.generator.internal.util.StringUtility;

import com.javass.jdbc.DatabaseCommentHelper;

/**
 * 
 * @author guojie
 * @datetime 2015年8月20日 下午5:11:58
 * @version 1.0
 */
public class MapperCommentGenerator implements CommentGenerator {

	private static final String PK_GENERATOR_TABLE_NAME = "sys_pk_generator";
	private static final String GeneratedValue = "@GeneratedValue(generator = \"%s\", strategy = GenerationType.TABLE)";
	// private static final String TableGenertor = "@TableGenerator(name = \"%s\", pkColumnValue = \"%s\", table = \""
	// + PK_GENERATOR_TABLE_NAME
	// + "\", pkColumnName = \"gen_name\", valueColumnName = \"gen_value\", initialValue = 1, allocationSize = 10)";
	private static final String TableGenertor = "@TableGenerator(name = \"%s\", pkColumnValue = \"%s\", table = TableGeneratorConstants.TABLE, pkColumnName = TableGeneratorConstants.PK_COLUMN_NAME, valueColumnName = TableGeneratorConstants.VALUE_COLUMN_NAME, initialValue = TableGeneratorConstants.initialValue, allocationSize = TableGeneratorConstants.allocationSize)";

	public MapperCommentGenerator() {
		super();
	}

	public void addJavaFileComment(CompilationUnit compilationUnit) {
		if (compilationUnit.isJavaInterface()) {
			// 改变 DAO 文件名称
			FullyQualifiedJavaType type = compilationUnit.getType();// baseShortName
			MetaObject metaObject = MetaObject.forObject(type, new DefaultObjectFactory(), new DefaultObjectWrapperFactory());
			metaObject.setValue("baseShortName", type.getShortName().replace("Mapper", "DAO"));
			metaObject.setValue("baseQualifiedName", type.getFullyQualifiedName().replace("Mapper", "DAO"));
			// System.out.println("addJavaFileComment");
		} else {

		}
		/*
		 * 
		 */
		compilationUnit.addFileCommentLine("/*");
		compilationUnit.addFileCommentLine(" * ");
		compilationUnit.addFileCommentLine(" * Copyright (c) zhuguojie Email:zhu915139481@126.com QQ:915139481");
		compilationUnit.addFileCommentLine(" * " + DateFormatUtils.format(new Date(), "yyyy年MM月dd日")
				+ " generated by mybatis-generator");
		compilationUnit.addFileCommentLine(" *");
		compilationUnit.addFileCommentLine(" *  Licensed under the Apache License, Version 2.0 (the \"License\");");
		compilationUnit.addFileCommentLine(" *  you may not use this file except in compliance with the License.");
		compilationUnit.addFileCommentLine(" *  You may obtain a copy of the License at");
		compilationUnit.addFileCommentLine(" *");
		compilationUnit.addFileCommentLine(" *      http://www.apache.org/licenses/LICENSE-2.0");
		compilationUnit.addFileCommentLine(" *");
		compilationUnit.addFileCommentLine(" *  Unless required by applicable law or agreed to in writing, software");
		compilationUnit.addFileCommentLine(" *  distributed under the License is distributed on an \"AS IS\" BASIS,");
		compilationUnit.addFileCommentLine(" *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.");
		compilationUnit.addFileCommentLine(" *  See the License for the specific language governing permissions and");
		compilationUnit.addFileCommentLine(" *  limitations under the License. ");
		compilationUnit.addFileCommentLine(" */");

	}

	/**
	 * xml中的注释
	 * 
	 * @param xmlElement
	 */
	public void addComment(XmlElement xmlElement) {
		// xmlElement.addElement(new TextElement("<!--"));
		// StringBuilder sb = new StringBuilder();
		// sb.append("  WARNING - ");
		// sb.append(MergeConstants.NEW_ELEMENT_TAG);
		// xmlElement.addElement(new TextElement(sb.toString()));
		// xmlElement.addElement(new TextElement("-->"));
	}

	public void addRootComment(XmlElement rootElement) {
		return;
	}

	public void addConfigurationProperties(Properties properties) {
	}

	/**
	 * 删除标记
	 * 
	 * @param javaElement
	 * @param markAsDoNotDelete
	 */
	protected void addJavadocTag(JavaElement javaElement, boolean markAsDoNotDelete) {
		StringBuilder sb = new StringBuilder();
		sb.append(" * ");
		sb.append(MergeConstants.NEW_ELEMENT_TAG);
		if (markAsDoNotDelete) {
			sb.append(" do_not_delete_during_merge");
		}
		javaElement.addJavaDocLine(sb.toString());
	}

	/**
	 * Example使用
	 * 
	 * @param innerClass
	 * @param introspectedTable
	 */
	public void addClassComment(InnerClass innerClass, IntrospectedTable introspectedTable) {
		if (innerClass.getJavaDocLines().size() > 0) {
			return;
		}
		addModelComment(innerClass, introspectedTable, false);
		// 增加父类泛型
		addParameterType(innerClass, introspectedTable);
	}

	public void addModelComment(InnerClass innerClass, IntrospectedTable introspectedTable, boolean isPKClass) {
		String remarks = getTableRemarks(introspectedTable);
		if (isPKClass)
			remarks = remarks + " 的 主键";
		innerClass.addJavaDocLine("/**");
		innerClass.addJavaDocLine(" * " + introspectedTable.getTableConfiguration().getTableName() + " : " + remarks);
		innerClass.addJavaDocLine(" * @author zhuguojie，zhu915139481@126.com");
		innerClass.addJavaDocLine(" * @date " + DateFormatUtils.format(new Date(), "yyyy年MM月dd日 "));
		innerClass.addJavaDocLine(" * @version 1.0");
		innerClass.addJavaDocLine(" */");
	}

	// 增加父类泛型
	private void addParameterType(InnerClass innerClass, IntrospectedTable introspectedTable) {
		List<IntrospectedColumn> primaryKeyColumns = introspectedTable.getPrimaryKeyColumns();
		// 指定了 父类
		if (innerClass.getSuperClass() != null && primaryKeyColumns.size() == 1) {
			String pkType = (primaryKeyColumns.size() > 1 ? introspectedTable.getPrimaryKeyType() : primaryKeyColumns.get(0)
					.getFullyQualifiedJavaType().getFullyQualifiedName());
			innerClass.getSuperClass().addTypeArgument(new FullyQualifiedJavaType(pkType));
		}
	}

	public String getTableRemarks(IntrospectedTable introspectedTable) {
		String remarks = "";
		try {
			remarks = DatabaseCommentHelper.getTableComment(introspectedTable);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return remarks;
	}

	public void addEnumComment(InnerEnum innerEnum, IntrospectedTable introspectedTable) {
	}

	/**
	 * 给字段添加数据库备注
	 * 
	 * @param field
	 * @param introspectedTable
	 * @param introspectedColumn
	 */
	public void addFieldComment(Field field, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) {
		try {
			// List<GeneratedJavaFile> javaFiles = introspectedTable.getGeneratedJavaFiles();
			// for (GeneratedJavaFile generatedJavaFile : javaFiles) {
			// CompilationUnit compilationUnit = generatedJavaFile.getCompilationUnit();
			// if (!compilationUnit.isJavaInterface() && compilationUnit.isJavaEnumeration()
			// && compilationUnit instanceof TopLevelClass) {
			// TopLevelClass topLevelClass = (TopLevelClass) compilationUnit;
			// addClassComment(topLevelClass, introspectedTable);
			// }
			// }
			if (!StringUtility.stringHasValue(introspectedColumn.getRemarks())) {// 无注释
				try {
					introspectedColumn.setRemarks(DatabaseCommentHelper.getColumnComment(introspectedTable, introspectedColumn));
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
			if (StringUtility.stringHasValue(introspectedColumn.getRemarks())) {
				field.addJavaDocLine("/**");
				StringBuilder sb = new StringBuilder();
				sb.append(" * ");
				sb.append(introspectedColumn.getRemarks());
				field.addJavaDocLine(sb.toString());
				field.addJavaDocLine(" */");
			}
			// 添加注解
			if (field.isTransient()) {
				// @Column
				field.addAnnotation("@Transient");
			}
			for (IntrospectedColumn column : introspectedTable.getPrimaryKeyColumns()) {
				if (introspectedColumn == column) {
					field.addAnnotation("@Id");
					break;
				}
			}
			String column = introspectedColumn.getActualColumnName();
			if (StringUtility.stringContainsSpace(column)
					|| introspectedTable.getTableConfiguration().isAllColumnDelimitingEnabled()) {
				column = introspectedColumn.getContext().getBeginningDelimiter() + column
						+ introspectedColumn.getContext().getEndingDelimiter();
			}
			field.addAnnotation("@Column(name = \"" + column + "\")");
			if (!column.equals(introspectedColumn.getJavaProperty())) {
				// @Column
			}
			List<IntrospectedColumn> primaryKeyColumns = introspectedTable.getPrimaryKeyColumns();
			if (primaryKeyColumns.size() == 1
					&& primaryKeyColumns.contains(introspectedColumn)
					&& ("DECIMAL".equalsIgnoreCase(introspectedColumn.getJdbcTypeName()) || "INTEGER"
							.equalsIgnoreCase(introspectedColumn.getJdbcTypeName()))) {// 单个主键，非联合主键，提供主键的生成策略
				// String generatorName = introspectedTable.getFullyQualifiedTableNameAtRuntime().toLowerCase();
				// int index = generatorName.indexOf("_");
				// generatorName = (index > 0 ? generatorName.substring(index + 1) : generatorName) + "_pkid";
				// String name = introspectedTable.getTableConfiguration().getDomainObjectName().toLowerCase() + "Generator";
				// field.addAnnotation("@CallableGenerator(name=\"" + name +
				// "\", callableName=\"pk_generatedKey\", parameters = {"
				// + "@CallableParameter(callableType = CallableParameterType.IN, value = \"" + generatorName + "\"),"
				// + "@CallableParameter(callableType = CallableParameterType.OUT, jdbcType = Types.DECIMAL) })");
				String domainObjectName = introspectedTable.getTableConfiguration().getDomainObjectName();
				String generatorName = domainObjectName + "_Generator";
				String generatorValue = domainObjectName + "_PKID";
				field.addAnnotation(String.format(GeneratedValue, generatorName));
				field.addAnnotation(String.format(TableGenertor, generatorName, generatorValue));
			}
			if (introspectedColumn.isIdentity()) {
				// if (introspectedTable.getTableConfiguration().getGeneratedKey().getRuntimeSqlStatement().equals("JDBC")) {
				// field.addAnnotation("@GeneratedValue(generator = \"JDBC\")");
				// } else {
				// field.addAnnotation("@GeneratedValue(strategy = GenerationType.IDENTITY)");
				// }
			} else if (introspectedColumn.isSequenceColumn()) {
				// field.addAnnotation("@SequenceGenerator(name=\"\",sequenceName=\""
				// + introspectedTable.getTableConfiguration().getGeneratedKey().getRuntimeSqlStatement() + "\")");
			} else {
				// @GeneratedValue(generator = "pk_generator", strategy = GenerationType.TABLE)
				// @TableGenerator(name = "pk_generator", schema = "jsldxh", table = "tb_pk_generator", pkColumnName = "gen_name",
				// valueColumnName = "gen_value", pkColumnValue = "department_pkid", allocationSize = 1, initialValue = 1)
			}
		} catch (Exception e) {
		}
	}

	/**
	 * Example使用
	 * 
	 * @param field
	 * @param introspectedTable
	 */
	public void addFieldComment(Field field, IntrospectedTable introspectedTable) {
	}

	/**
	 * @param method
	 * @param introspectedTable
	 */
	public void addGeneralMethodComment(Method method, IntrospectedTable introspectedTable) {
		// System.out.println("addGeneralMethodComment");
	}

	/**
	 * getter方法注释
	 * 
	 * @param method
	 * @param introspectedTable
	 * @param introspectedColumn
	 */
	public void addGetterComment(Method method, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) {
		// if (!StringUtility.stringHasValue(introspectedColumn.getRemarks()))
		// return;
		// StringBuilder sb = new StringBuilder();
		// method.addJavaDocLine("/**");
		// if (StringUtility.stringHasValue(introspectedColumn.getRemarks())) {
		// sb.append(" * 获取");
		// sb.append(introspectedColumn.getRemarks());
		// method.addJavaDocLine(sb.toString());
		// method.addJavaDocLine(" *");
		// }
		// sb.setLength(0);
		// sb.append(" * @return ");
		// sb.append(introspectedColumn.getActualColumnName());
		// if (StringUtility.stringHasValue(introspectedColumn.getRemarks())) {
		// sb.append(" - ");
		// sb.append(introspectedColumn.getRemarks());
		// }
		// method.addJavaDocLine(sb.toString());
		// method.addJavaDocLine(" */");
	}

	/**
	 * setter方法注释
	 * 
	 * @param method
	 * @param introspectedTable
	 * @param introspectedColumn
	 */
	public void addSetterComment(Method method, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) {
		// if (!StringUtility.stringHasValue(introspectedColumn.getRemarks()))
		// return;
		// StringBuilder sb = new StringBuilder();
		// method.addJavaDocLine("/**");
		// if (StringUtility.stringHasValue(introspectedColumn.getRemarks())) {
		// sb.append(" * 设置");
		// sb.append(introspectedColumn.getRemarks());
		// method.addJavaDocLine(sb.toString());
		// method.addJavaDocLine(" *");
		// }
		// Parameter parm = method.getParameters().get(0);
		// sb.setLength(0);
		// sb.append(" * @param ");
		// sb.append(parm.getName());
		// if (StringUtility.stringHasValue(introspectedColumn.getRemarks())) {
		// sb.append(" ");
		// sb.append(introspectedColumn.getRemarks());
		// }
		// method.addJavaDocLine(sb.toString());
		// method.addJavaDocLine(" */");
	}

	/**
	 * Example使用
	 * 
	 * @param innerClass
	 * @param introspectedTable
	 * @param markAsDoNotDelete
	 */
	public void addClassComment(InnerClass innerClass, IntrospectedTable introspectedTable, boolean markAsDoNotDelete) {
		this.addClassComment(innerClass, introspectedTable);
	}

	public void addClassComment(Interface inter, IntrospectedTable introspectedTable) {
		String remarks = getTableRemarks(introspectedTable);
		inter.addJavaDocLine("/**");
		inter.addJavaDocLine(" * " + introspectedTable.getTableConfiguration().getTableName() + " : " + remarks);
		inter.addJavaDocLine(" * " + introspectedTable.getTableConfiguration().getDomainObjectName() + " : 数据存储 ");
		inter.addJavaDocLine(" * @author zhuguojie，zhu915139481@126.com");
		inter.addJavaDocLine(" * @date " + DateFormatUtils.format(new Date(), "yyyy年MM月dd日"));
		inter.addJavaDocLine(" * @version 1.0");
		inter.addJavaDocLine(" */");
	}

}
